package org.hibernate.transform;

import java.util.List;

import org.apache.commons.lang.ArrayUtils;
import org.hibernate.HibernateException;
import org.sothis.util.bean.BeanAccessor;

@SuppressWarnings("serial")
public class CustomAliasToBeanResultTransformer implements ResultTransformer
{
    private final Class<?> resultClass;

    public CustomAliasToBeanResultTransformer(Class<?> clazz)
    {
        super();
        this.resultClass = clazz;
    }

    public Object transformTuple(Object[] tuple, String[] aliases)
    {
        Object resultBean;
        try
        {
            resultBean = resultClass.newInstance();
            for (int i = 0; i<tuple.length; i++)
            {
                String alias = aliases[i];

                String[] aliasArray = alias.split("_");

                if (alias!=null)
                {
                    processResult(resultBean, aliasArray, tuple[i]);
                }
                else
                {
                    throw new NullPointerException("Alias must be specified");
                }
            }
        }
        catch (InstantiationException e)
        {
            e.printStackTrace();
            throw new HibernateException("Could not instantiate resultclass: "
                +resultClass.getName());
        }
        catch (IllegalAccessException e)
        {
            e.printStackTrace();
            throw new HibernateException("Could not instantiate resultclass: "
                +resultClass.getName());
        }

        return resultBean;
    }

    @SuppressWarnings("unchecked")
    public List transformList(List collection)
    {
        return collection;
    }

    /**
     * 根据别名填充resultBean，别名如果有嵌套，使用下划线代替点，比如as
     * avatarView_serverSideLocation，因为hibernate解析不支持点。理论上可以无限嵌套。
     */
    private void processResult(Object resultBean, String[] aliasArray,
        Object value)
    {
        int layerLength = aliasArray.length;

        if (1==layerLength)
        {
            BeanAccessor.setValue(resultBean, aliasArray[0], value);
        }
        else
        {
            try
            {
                Object innerBean = BeanAccessor.getValue(resultBean,
                    aliasArray[0]);
                if (null==innerBean)
                {
                    // 内部嵌套的bean初始值是null，需要对它进行初始化。下面三句等同于avatarView=new
                    // AvatarView();userView.setAvatarView(avatarView);
                    Class<?> innerBeanClass = BeanAccessor.getPropertyClass(
                        resultBean, aliasArray[0]);
                    innerBean = innerBeanClass.newInstance();
                    BeanAccessor.setValue(resultBean, aliasArray[0], innerBean);
                }
                processResult(innerBean, (String[])ArrayUtils.remove(
                    aliasArray, 0), value);
            }
            catch (InstantiationException e)
            {
                e.printStackTrace();
            }
            catch (IllegalAccessException e)
            {
                e.printStackTrace();
            }
        }
    }
}
